package com.wenkaihu.android.chess.view;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Point;
import android.view.Display;
import android.view.MotionEvent;

public class GoBang extends CoordinateView {
	// definition of the max line number
	private final static int LINE_STEP = 5;
	// the result of check pieces
	private final static int DRAW = 0;
	private final static int WHITE_WIN = 1;
	private final static int BLACK_WIN = 2;
	// definition of the sign
	
//	private final static int POSITIVE = 1;
//	private final static int NEGATIVE = -1;

	private Context mCtx;
	// constructor method
	public GoBang(Context context, Display display) {
		super(context, display);
		mCtx = context;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		super.onTouchEvent(event);
		showResult(pieces);
		return false;
	}
	
	public void showResult(ArrayList<Point> pieces){
		switch (checkThePieces(pieces)) {
		case DRAW:
			break;
		case WHITE_WIN:
			new AlertDialog.Builder(mCtx).setTitle("White Win!").setMessage("Click Ok Play Again!")
				.setPositiveButton("OK",
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog,
								int whichButton) {
							GoBang.super.pieces.clear();
							refresh();
						}
					}).show();
			break;
		case BLACK_WIN:
			new AlertDialog.Builder(mCtx).setTitle("Black Win!").setMessage("Click Ok Play Again!")
			.setPositiveButton("OK",
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog,
							int whichButton) {
						GoBang.super.pieces.clear();
						refresh();
					}
				}).show();
			break;
		default:
			break;
		}
		refresh();
	}
	
	/**
	 * check the current pieces if there have a side get win
	 * 
	 * @param pieces   all of current pieces
	 * @return integer include DRAW, WHITE_WIN, BLACK_WIN
	 */
	public int checkThePieces(ArrayList<Point> pieces) {
		ArrayList<Point> whites = new ArrayList<Point>();
		ArrayList<Point> blacks = new ArrayList<Point>();
		// get the black & white pieces
		for (Point point : pieces) {
			if (pieces.indexOf(point) % 2 == 0) {
				whites.add(point);
			} else {
				blacks.add(point);
			}
		}
		// check the white pieces
		for (Point point : whites) {
			if (isPartOfLine(LINE_STEP, point, whites)) {
				return WHITE_WIN;
			}
		}
		// check the black pieces
		for (Point point : blacks) {
			if (isPartOfLine(LINE_STEP, point, blacks)) {
				return BLACK_WIN;
			}
		}

		return DRAW;
	}

	/**
	 * check current point, if it is part of the succussed line
	 * 
	 * @param step    the line step
	 * @param point   current point
	 * @param pieces  the black or white pieces collection
	 */
	public boolean isPartOfLine(int step, Point point, ArrayList<Point> pieces) {
		// check the x, y, r, l direction
		return checkXDirection(point, pieces, 1) || checkYDirection(point, pieces, 1) 
			|| checkRDirection(point, pieces, 1) || checkLDirection(point, pieces, 1);
		
	}
	
	/** 
	 * recursion the x direction to check
	 * @param  i 	    the total pieces had been checked
	 * @param  pieces   all the pieces 
	 * @param  point    the base point
	 * @return boolean  the result of x direction check
	 */
	public boolean checkXDirection(Point point, ArrayList<Point> pieces, int i){
		if (point.x + i < xCount && pieces.contains(new Point(point.x + i, point.y))) {
			if (i < LINE_STEP - 1){
				return checkXDirection(point, pieces, ++i);
			}else{
				return true;
			}
		} else {
			return spreadLineX(point.x, point.y, LINE_STEP - (i - 1), pieces);
		}
	}
	
	public boolean checkRDirection(Point point, ArrayList<Point> pieces, int i){
		if (((point.x + i < xCount) && (point.y - i >= 0)) 
				&& pieces.contains(new Point(point.x + i, point.y - i))) {
			if (i < LINE_STEP - 1){
				return checkXDirection(point, pieces, ++i);
			}else{
				return true;
			}
		} else {
			return spreadLineR(point.x, point.y, LINE_STEP - (i - 1), pieces);
		}
	}

	public boolean checkLDirection(Point point, ArrayList<Point> pieces, int i){
		if (((point.x + i < xCount) && (point.y + i < yCount)) 
				&& pieces.contains(new Point(point.x + i, point.y + i))) {
			if (i < LINE_STEP - 1){
				return checkXDirection(point, pieces, ++i);
			}else{
				return true;
			}
		} else {
			return spreadLineL(point.x, point.y, LINE_STEP - (i - 1), pieces);
		}
	}

	public boolean checkYDirection(Point point, ArrayList<Point> pieces, int i){
		if (point.y + i < yCount && pieces.contains(new Point(point.x, point.y + i))) {
			if (i < LINE_STEP - 1){
				return checkXDirection(point, pieces, ++i);
			}else{
				return true;
			}
		} else {
			return spreadLineY(point.x, point.y, LINE_STEP - (i - 1), pieces);
		}
	}
	
	/**
	 * check the x direction if there has continue length - 1 point in the
	 * collection
	 * @param  x,y     the x, y of the point
	 * @param  sign    the POSITIVE or NEGATIVE value
	 * @param  pieces  the black or white pieces collection
	 * @return boolean the result of checked
	 */
	public boolean spreadLineX(int x, int y, int length, ArrayList<Point> pieces) {
		for (int i = 1; i < length; i++) {
			if((x - i < 0) || !pieces.contains(new Point(x - i, y))){
				return false;
			}
		}
		return true;
	}
	
	public boolean spreadLineY(int x, int y, int length, ArrayList<Point> pieces) {
		for (int i = 1; i < length; i++) {
			if((y - i < 0) || !pieces.contains(new Point(x, y - i))){
				return false;
			}
		}
		return true;
	}
	
	public boolean spreadLineL(int x, int y, int length, ArrayList<Point> pieces) {
		for (int i = 1; i < length; i++) {
			if((y - i < 0) || (x - i) < 0 || !pieces.contains(new Point(x - i, y - i))){
				return false;
			}
		}
		return true;
	}	
	
	public boolean spreadLineR(int x, int y, int length, ArrayList<Point> pieces) {
		for (int i = 1; i < length; i++) {
			if((y + i >= yCount) || (x - i < 0) || !pieces.contains(new Point(x - i, y + i))){
				return false;
			}
		}
		return true;
	}
}
